package homework;

import java.io.*;

/**
 * @Author: fanbo
 * @Date: 2021/1/25 5:48 上午
 */
public class WebAppLoader extends ClassLoader {
    /**
     * classes:表示加载的文件是单纯的class文件
     * 类似tomcat就是{PROJECT}/classes/
     */
    private String classes;


    /**
     * 只需要指定项目路径就好
     * 默认class加载路径是目录下{PROJECT}/WEB-INF/classes/
     *
     * @param webPath
     */
    public WebAppLoader(String webPath) {
        classes = webPath + "/classes/";
    }

    @Override
    public Class<?> loadClass(String name) throws ClassNotFoundException {
        Class<?> aClass = super.loadClass(name);
        if (aClass != null) {
            return aClass;
        }
        return findClass(name);
    }

    /**
     * 按照父类的机制，如果在父类中没有找到的类
     * 才会调用这个findClass来加载
     * 这样只会加载放在自己目录下的文件
     * 而系统自带需要的class并不是由这个加载
     */
    @Override
    protected Class<?> findClass(String name) {
        System.out.println("findClass: " + name);
        try {
            byte[] result = getClassFromFile(name);
            if (result == null) {
                throw new FileNotFoundException();
            } else {
                Class<?> aClass = defineClass(name, result, 0, result.length);
                return aClass;
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 从指定的classes文件夹下找到文件
     *
     * @param name
     * @return
     */
    private byte[] getClassFromFile(String name) {
        String classPath = classes + name.replace('.', File.separatorChar) + ".class";
        File file = new File(classPath);
        if (file.exists()) {
            InputStream input = null;
            try {
                input = new FileInputStream(file);
                ByteArrayOutputStream baos = new ByteArrayOutputStream();
                int bufferSize = 4096;
                byte[] buffer = new byte[bufferSize];
                int bytesNumRead = 0;
                while ((bytesNumRead = input.read(buffer)) != -1) {
                    baos.write(buffer, 0, bytesNumRead);
                }
                return baos.toByteArray();
            } catch (FileNotFoundException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            } finally {
                if (input != null) {
                    try {
                        input.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }

        }
        return null;
    }
}
